/*
 * @(#)TreeExplorer.java 0.0.1-SNAPSHOT
 *
 * Copyright Group B
 */
package grupb.upf.gui;

import java.io.File;
import java.io.FileFilter;
import java.util.Enumeration;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * <p>This is the Tree Explorer.</p>
 *
 * @version    0.0.1-SNAPSHOT
 * @author     Group B
 */
public final class TreeExplorer extends javax.swing.JPanel {

    /**
     * The logger. A new logger <code>grupb.upf.gui.TreeExplorer</code>
     * is created to add the logs of this TreeExplorer.
     */
    private static final Log LOG = LogFactory.getLog(TreeExplorer.class);
    /**
     * Tree icons size by default.
     */
    private static final int DEFAULT_TREE_ICON_SIZE = 20;
    /**
     * Tree icon size.
     */
    private int iconSizeTree = DEFAULT_TREE_ICON_SIZE;
    /**
     * The initial of the tree.
     */
    private P2Piki p2piki;
    /**
     * The type of folders (image [2] or video [3] folders).
     */
    private int type;
    /**
     * The main GUI.
     */
    DefaultMutableTreeNode top;
    /**
     * Creates a new TreeExplorer.
     * @param p2p the main GUI
     * @param t the type of folders
     */
    public TreeExplorer(final P2Piki p2p, final int t) {
        this.type = t;
        String folder = "";
        switch (type) {
            case 0:
                folder = "photo.folder";
                break;
            case 1:
                folder = "video.folder";
                break;
            default:
                break;
        }
        this.p2piki = p2p;
        File f = new File(grupb.upf.util.Config.getProperty(folder));
        /**
         * DefaultMutableTreeNode the class which let us to add and remove
         * nodes.
         */
        top = new DefaultMutableTreeNode(f) {

            @Override
            public String toString() {
                if (userObject == null) {
                    return null;
                } else if (userObject instanceof File) {
                    return ((File) userObject).getName();
                } else {
                    return userObject.toString();
                }
            }
        };
        populateNode(top, f);
        initComponents();
        File[] files = f.listFiles(new FileFilter() {

            @Override
            public boolean accept(final File pathname) {
                return !pathname.getName().substring(0, 1).equals(".");
            }
        });
        if (files != null) {
            for (int i = 0; i < files.length; i++) {
                p2piki.listExplorerAddElement(type, files[i]);
            }
        }
    }

    /**
     * Method to change the default icons size.
     * @param size the new size of the icons
     */
    public void setIconSize(final int size) {
        this.iconSizeTree = size;
    }

    /**
     * Method to open de directory.
     * @param dir the directory to open
     */
    public void directorySelected(final File dir) {
        final TreeNode root =
                (TreeNode) treeTree.getModel().getRoot();
        buscaDirectory(root, dir);
    }

    /**
     * Recursive method to search the directory.
     * @param parent the parent directory
     * @param dir the directory to search
     */
    private void buscaDirectory(final TreeNode parent,
            final File dir) {
        DefaultMutableTreeNode node = (DefaultMutableTreeNode) parent;
        File f = (File) node.getUserObject();
        if (f.getAbsolutePath().equals(dir.getAbsolutePath())) {
            treeTree.setSelectionPath(new TreePath(node.getPath()));
            return;
        }
        if (parent.getChildCount() >= 0) {
            for (Enumeration e = parent.children(); e.hasMoreElements();) {
                TreeNode n = (TreeNode) e.nextElement();
                buscaDirectory(n, dir);
            }
        }
    }

    /**
     * Method to populate a node.
     * @param node the tree node to populate
     * @param f the file
     * @return true or false
     */
    private boolean populateNode(final DefaultMutableTreeNode node,
            final File f) {
        node.removeAllChildren();
        return populateNode(node, f, 2);
    }

    /**
     * Method to create the tree.
     * @param node the previous node
     * @param f the file
     * @param depth the depth that we want
     * @return if it is correct true and false if not
     */
    private boolean populateNode(final DefaultMutableTreeNode node,
            final File f, final int depth) {
        File[] files = f.listFiles(new FileFilter() {

            @Override
            public boolean accept(final File pathname) {
                return pathname.isDirectory() && !pathname.getName().substring(0, 1).equals(".");
            }
        });

        if (files != null && depth > 0) {
            for (int i = 0; i < files.length; i++) {
                DefaultMutableTreeNode curr =
                        new DefaultMutableTreeNode(files[i]) {

                            /**
                             * We rewrite the method toString() of the class
                             * File and use getName().
                             * @return the name of the file
                             */
                            @Override
                            public String toString() {
                                if (userObject == null) {
                                    return null;
                                } else if (userObject instanceof File) {
                                    return ((File) userObject).getName();
                                } else {
                                    return userObject.toString();
                                }
                            }
                        };
                populateNode(curr, files[i], depth - 1);
                node.add(curr);
            }
        }
        return true;
    }

    private void directorySelected() {
        DefaultMutableTreeNode node =
                (DefaultMutableTreeNode) treeTree
                .getLastSelectedPathComponent();
        if (node != null) {
            File f = (File) node.getUserObject();

            File[] files = f.listFiles(new FileFilter() {

                @Override
                public boolean accept(final File pathname) {
                    return !pathname.getName().substring(0, 1).equals(".");
                }
            });
            p2piki.listExplorerRemoveAllElements(type);
            if (files != null) {
                for (int i = 0; i < files.length; i++) {
                    p2piki.listExplorerAddElement(type, files[i]);
                }
            }
        }
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        treeScrollPane = new javax.swing.JScrollPane();
        treeTree = new javax.swing.JTree(top);

        setMaximumSize(new java.awt.Dimension(162, 600));
        setMinimumSize(new java.awt.Dimension(156, 525));
        setPreferredSize(new java.awt.Dimension(162, 600));

        treeScrollPane.setBorder(null);
        treeScrollPane.setMaximumSize(new java.awt.Dimension(162, 600));
        treeScrollPane.setMinimumSize(new java.awt.Dimension(157, 506));
        treeScrollPane.setPreferredSize(new java.awt.Dimension(162, 560));

        treeTree.setCellRenderer(new DirectoryRenderer(iconSizeTree));
        treeTree.setRowHeight(DEFAULT_TREE_ICON_SIZE);
        treeTree.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                treeTreeMouseClicked(evt);
            }
        });
        treeTree.addTreeExpansionListener(new javax.swing.event.TreeExpansionListener() {
            public void treeCollapsed(javax.swing.event.TreeExpansionEvent evt) {
            }
            public void treeExpanded(javax.swing.event.TreeExpansionEvent evt) {
                treeTreeTreeExpanded(evt);
            }
        });
        treeTree.addTreeSelectionListener(new javax.swing.event.TreeSelectionListener() {
            public void valueChanged(javax.swing.event.TreeSelectionEvent evt) {
                treeTreeValueChanged(evt);
            }
        });
        treeScrollPane.setViewportView(treeTree);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(treeScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(treeScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
        );
    }// </editor-fold>//GEN-END:initComponents

    private void treeTreeTreeExpanded(javax.swing.event.TreeExpansionEvent evt) {//GEN-FIRST:event_treeTreeTreeExpanded
        // TODO add your handling code here:
        TreePath path = evt.getPath();
        DefaultMutableTreeNode node =
                (DefaultMutableTreeNode) path.getLastPathComponent();

        if (node == null) {
            return;
        }
        File f = (File) node.getUserObject();
        populateNode(node, f);
        JTree tree = (JTree) evt.getSource();
        DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
        model.nodeStructureChanged(node);
    }//GEN-LAST:event_treeTreeTreeExpanded

    private void treeTreeValueChanged(javax.swing.event.TreeSelectionEvent evt) {//GEN-FIRST:event_treeTreeValueChanged
        // TODO add your handling code here:
        directorySelected();
    }//GEN-LAST:event_treeTreeValueChanged

    private void treeTreeMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_treeTreeMouseClicked
        // TODO add your handling code here:
        directorySelected();
        p2piki.showListExplorer(type);
    }//GEN-LAST:event_treeTreeMouseClicked
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JScrollPane treeScrollPane;
    private javax.swing.JTree treeTree;
    // End of variables declaration//GEN-END:variables
}
